<template>
  <div
    class="ui-cascader"
    :class="[{'is-editable': editable}, 'ui-cascader--' + size]"
  >
    <template v-if="editable">
      <el-cascader
        ref="control"
        class="ui-cascader__control"
        :size="size"
        :props="innerProps"
        :clearable="clearable"
        :placeholder="placeholder"
        v-model="innerValue"
        :options="options"
      ></el-cascader>
    </template>
    <template v-else>
      {{ showText }}
    </template>
  </div>
</template>
<script>
import Cascader from 'element-ui/lib/cascader'
import 'element-ui/lib/theme-chalk/cascader.css'
import { getNodeByValue, getClosestNodes } from './utils'

export default {
  name: 'UiCascader',
  components: {
    ElCascader: Cascader
  },
  props: {
    editable: {
      type: Boolean,
      default: true
    },
    clearable: {
      type: Boolean,
      default: false
    },
    multiple: {
      type: Boolean,
      default: false
    },
    textField: {
      type: String,
      default: 'text'
    },
    valueField: {
      type: String,
      default: 'value'
    },
    childrenField: {
      type: String,
      default: 'children'
    },
    value: {
      type: [String, Array],
      default: undefined
    },
    keepPath: {
      type: Boolean,
      default: true
    },
    size: {
      type: String,
      default: 'small'
    },
    placeholder: {
      type: String
    },
    queryMethod: {
      type: Function
    }
  },
  data() {
    return {
      loading: false,
      options: [],
      displayValue: ''
    }
  },
  computed: {
    innerValue: {
      get() {
        let value = this.value
        if (!this.keepPath) {
          if (!Array.isArray(value)) {
            const closestNodes = getClosestNodes(value, this.options, this.valueField, this.childrenField).reverse()
            value = closestNodes.map(v => v[this.valueField])
          }
        }
        return value
      },
      set(val) {
        if (!this.keepPath) {
          if (Array.isArray(val)) {
            val = val[val.length - 1]
          }
        }
        this.$emit('input', val)
        if (!val || !val.length) {
          this.$emit('change', {
            value: val,
            closestItems: null
          })
        } else {
          this.$emit('change', {
            value: val,
            closestItems: getClosestNodes(val, this.options, this.valueField, this.childrenField)
          })
        }
      }
    },
    innerProps() {
      return {
        label: this.textField,
        value: this.valueField,
        children: this.childrenField
      }
    },
    showText() {
      if (!this.innerValue) {
        return
      }
      if (!this.innerValue.length) {
        return
      }
      return this.innerValue.map(val => {
        const node = getNodeByValue(val, this.options, this.valueField, this.childrenField)
        if (!node) {
          return val
        } else {
          return node[this.textField]
        }
      }).join(' / ')
    },
    isEmpty() {
      return !this.value || !this.value.length
    }
  },
  created() {
    this.loadOptions()
  },
  methods: {
    loadOptions() {
      if (!this.queryMethod) {
        return Promise.reject()
      }
      this.loading = true
      this.queryMethod().then(rs => {
        this.options = rs
      }).finally(() => {
        this.loading = false
      })
    },
    handleClearClick() {
      this.innerValue = null
    }
  }
}
</script>
<style lang="less">
.ui-cascader__control{
  width: 100%;
}
.ui-cascader{
  font-size: 14px;
}
</style>
